package org.cloudie.docs.editor.client.widgets;

import org.cloudie.docs.editor.client.behaviors.HasDragBehavior;
import org.cloudie.docs.editor.client.behaviors.HasDropBehavior;
import org.cloudie.docs.editor.client.behaviors.HasReceiveBehavior;
import org.cloudie.docs.editor.client.commands.Command;
import org.cloudie.docs.editor.client.managers.DropReceiveManager;
import org.cloudie.docs.editor.client.resources.icons.IconsHelper;

import com.allen_sauer.gwt.dnd.client.HasDragHandle;
import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.google.gwt.event.dom.client.ContextMenuEvent;
import com.google.gwt.event.dom.client.ContextMenuHandler;
import com.google.gwt.event.dom.client.HasContextMenuHandlers;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.CellPanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public abstract class Icon extends Composite
	implements HasDragHandle, HasContextMenuHandlers,
    HasDragBehavior, HasDropBehavior,
    HasReceiveBehavior {

  protected HandlerManager manager;
  protected DropReceiveManager dropManager;
  protected PickupDragController registeredDragController;
  protected Image icon;
  protected FocusPanel container;
  protected Label label;
  protected String image;
  protected Command command;
  protected String id;
  protected boolean isSmall;
	  
  protected Icon(String id, String label, String image, boolean isSmall,
      String tooltip, boolean vertical, Command cmd) {
	this.id = id;
	this.isSmall = isSmall;
    this.image = image;
    this.command = cmd;
    this.label = new Label(label);
    this.label.addStyleName("label");
    manager = new HandlerManager(this);
    this.sinkEvents(Event.ONCONTEXTMENU);
    CellPanel content;
    if (vertical) {
      VerticalPanel pan = new VerticalPanel();
      pan.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
      content = pan;
    } else {
      HorizontalPanel pan = new HorizontalPanel();
      pan.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
      content = pan;
    }
    icon = IconsHelper.getIcon(image, isSmall);
    content.setSize("100%", "100%");
    content.add(icon);
    content.add(this.label);
    content.setCellWidth(icon, "20px");
    this.container = new FocusPanel();
    this.container.setTitle(tooltip);
    this.container.add(content);
    initWidget(this.container);
	this.dropManager = new DropReceiveManager(this);
  }
  
  public void setStyle(String labelColor, String labelBgColor) {
	this.label.getElement().getStyle().setColor(labelColor);
	this.label.getElement().getStyle().setBackgroundColor(labelBgColor);
  }
	
  @Override
  public void onBrowserEvent(Event event) {
    if (event.getTypeInt() == Event.ONCONTEXTMENU) {
      event.preventDefault();
      event.stopPropagation();
      ContextMenuEvent.fireNativeEvent(event, this);
    }
    super.onBrowserEvent(event);
  }
	
  @Override
  public void fireEvent(GwtEvent<?> event) {
    manager.fireEvent(event);
  }

  @Override
  public HandlerRegistration addContextMenuHandler(ContextMenuHandler handler) {
    return manager.addHandler(ContextMenuEvent.getType(), handler);
  }
	
  public Command getCommand() {
    return command;
  }
	
  public void setCommand(Command command) {
    this.command = command;
  }

  public String getLabel() {
    return label.getText();
  }

  public void setLabel(String label) {
    this.label.setText(label);
  }

  public String getTooltip() {
    return container.getTitle();
  }

  public String getImage() {
    return image;
  }

  public void setImage(String image) {
	this.image = image;
	this.icon.setUrl(IconsHelper.getIconUrl(image, this.isSmall));
  }

  public String getId() {
    return id;
  }
  
  public void setId(String id) {
    this.id = id;
  }

  public boolean isSmall() {
    return isSmall;
  }

  public void setSmall(boolean isSmall) {
    this.isSmall = isSmall;
  }

  @Override
  public abstract Widget getDragHandle();

  @Override
  public boolean allowsDropping(Widget receiver) {
  	return true;
  }

  @Override
  public boolean allowsDropping() {
  	return true;
  }
  
  @Override
  public void onDropCanceled() {
  }

  @Override
  public void onDropped(Widget receiver, int x, int y) {
    registeredDragController.unregisterDropController(dropManager);
  }
  
  @Override
  public boolean acceptsReceives(Widget dropped, boolean isFinal) {
	return false;
  }

  @Override
  public boolean acceptsReceives() {
  	return false;
  }

  @Override
  public void onReceive(Widget dropped, int x, int y) {
  }

  @Override
  public DropReceiveManager getDropReceiveManager() {
  	return dropManager;
  }
  
  @Override
  public void setDragController(PickupDragController controller) {
    controller.registerDropController(dropManager);
    registeredDragController = controller;
  }
  
  @Override
  public PickupDragController getDragController() {
    return registeredDragController;
  }
  
  @Override
  public void onLoad() {
    super.onLoad();
    if (registeredDragController != null) {
      registeredDragController.registerDropController(dropManager);
    }
  }
  
  @Override
  public void onUnload() {
    super.onUnload();
    if (registeredDragController != null) {
      registeredDragController.unregisterDropController(dropManager);
    }
  }
}
